package common.bean;


import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.HibernateException;
import org.hibernate.property.ChainedPropertyAccessor;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;

import java.util.Arrays;

public class VoResultTransformer extends AliasedTupleSubsetResultTransformer {
    private final Class resultClass;
    private boolean isInitialized;
    private String[] aliases;

    public VoResultTransformer(Class resultClass) {
        if (resultClass == null) {
            throw new IllegalArgumentException("resultClass cannot be null");
        }
        isInitialized = false;
        this.resultClass = resultClass;
    }


    public Object transformTuple(Object[] tuple, String[] aliases) {
        Object result;

        try {
            if (!isInitialized) {
                initialize(aliases);
            } else {
                //check( aliases );
            }

            result = resultClass.newInstance();

            for (int i = 0; i < aliases.length; i++) {
                try {
                    BeanUtils.setProperty(result, this.aliases[i], tuple[i]);
                } catch (Exception e) {
                    System.out.println("VoResultTransformer-transformTupleException-" + resultClass.getName() + "---" + this.aliases[i]);
                }
            }
        } catch (InstantiationException e) {
            throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
        } catch (IllegalAccessException e) {
            throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
        }

        return result;
    }

    private void check(String[] aliases) {
        if (!Arrays.equals(aliases, this.aliases)) {
            throw new IllegalStateException(
                    "aliases are different from what is cached; aliases=" + Arrays.asList(aliases) +
                            " cached=" + Arrays.asList(this.aliases));
        }
    }

    public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
        return false;
    }

    private String convertAlias(String alias) {
        String[] tmp = alias.split("_");
        String result = null;
        for (int n = 0; n < tmp.length; n++) {
            if (n == 0) {
                result = tmp[n].toLowerCase();
            } else {
                result += tmp[n].substring(0, 1) + tmp[n].substring(1).toLowerCase();
            }
        }
        return result;
    }

    private void initialize(String[] aliases) {
        PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(
                new PropertyAccessor[]{
                        PropertyAccessorFactory.getPropertyAccessor(resultClass, null),
                        PropertyAccessorFactory.getPropertyAccessor("field")
                }
        );
        this.aliases = new String[aliases.length];
        for (int i = 0; i < aliases.length; i++) {
            String alias = convertAlias(aliases[i]);
            if (alias != null) {
                    this.aliases[i] = alias;
            }
        }
        isInitialized = true;
    }
}
